package com.gitee.fastmybatis.core;

import com.gitee.fastmybatis.core.ext.info.TableInfo;
import com.gitee.fastmybatis.core.util.ClassUtil;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author tanghc
 */
public class MybatisContext {

    public static final String MAIN_DS_ALIAS = "_ds_main_";

    // key: entityClass, value: mapperClass
    private static final Map<Class<?>, Class<?>> entityMapper = new HashMap<>(16);

    // key：mapperClass, value: entityClass
    private static final Map<Class<?>, Class<?>> mapperEntity = new HashMap<>(16);

    // key: mapperClass
    private static final Map<Class<?>, SqlSessionFactory> sqlSessionFactoryMapForMapper = new HashMap<>();
    // key: dsAlias
    private static final Map<String, SqlSessionFactory> sqlSessionFactoryMapForDsAlias = new HashMap<>();

    // KEY: mapperClass
    private static final Map<Class<?>, TableInfo> tableInfoMap = new HashMap<>();

    public static void addSqlSessionFactory(String dsAlias, SqlSessionFactory sqlSessionFactory, boolean main) {
        if (main) {
            dsAlias = MAIN_DS_ALIAS;
        }
        sqlSessionFactoryMapForDsAlias.put(dsAlias, sqlSessionFactory);
    }

    public static SqlSessionFactory getMainSqlSessionFactory() {
        return sqlSessionFactoryMapForDsAlias.get(MAIN_DS_ALIAS);
    }


    /**
     * 根据数据源别名获取SqlSessionFactory
     *
     * @param dsAlias 数据源别名
     * @return 返回SqlSessionFactory
     */
    public static SqlSessionFactory getSqlSessionFactoryByDataSourceAlias(String dsAlias) {
        if (dsAlias == null) {
            dsAlias = MAIN_DS_ALIAS;
        }
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryMapForDsAlias.get(dsAlias);
        if (sqlSessionFactory == null) {
            sqlSessionFactory = sqlSessionFactoryMapForDsAlias.get(MAIN_DS_ALIAS);
        }
        return sqlSessionFactory;
    }

    public static void addMapperClass(Collection<Class<?>> mapperClasses) {
        for (Class<?> mapperClass : mapperClasses) {
            Class<?> entityClass = getEntityClass(mapperClass);
            entityMapper.put(entityClass, mapperClass);
            mapperEntity.put(mapperClass, entityClass);
        }
    }

    public static Class<?> getMapperClassByEntityClass(Class<?> entityClass) {
        return entityMapper.get(entityClass);
    }

    public static Class<?> getEntityClassByMapperClass(Class<?> mapperClass) {
        mapperClass = ClassUtil.getRealMapperClass(mapperClass);
        return mapperEntity.get(mapperClass);
    }

    private static Class<?> getEntityClass(Class<?> mapperClass) {
        String name = mapperClass.getName();
        if (mapperClass.isInterface() || name.startsWith(ClassUtil.PROXY_PREFIX)) {
            return ClassUtil.getSuperInterfaceGenericType(mapperClass, 0);
        } else {
            return ClassUtil.getSuperClassGenericType(mapperClass, 0);
        }
    }

    public static void addSqlSessionFactory(Class<?> mapperClass, SqlSessionFactory sqlSessionFactory) {
        sqlSessionFactoryMapForMapper.put(mapperClass, sqlSessionFactory);
    }

    /**
     * 根据Mapper获取对应的SqlSessionFactory
     *
     * @param mapperClass Mapper class
     * @return 返回SqlSessionFactory
     */
    public static SqlSessionFactory getSqlSessionFactoryByMapperClass(Class<?> mapperClass) {
        return sqlSessionFactoryMapForMapper.get(mapperClass);
    }

    public static void addTableInfo(Class<?> mapperClass, TableInfo tableInfo) {
        tableInfoMap.put(mapperClass, tableInfo);
    }

    public static TableInfo getTableInfo(Class<?> mapperClass) {
        return tableInfoMap.get(mapperClass);
    }

    public static void clearTableInfo() {
        tableInfoMap.clear();
    }
}
